package com.arturjaneczko.view.core;

import java.awt.Container;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Observable;

import javax.swing.JPanel;

import com.arturjaneczko.model.core.IModel;

public abstract class AView implements IView {

	private Class<Container> $class;
	protected List<IView> compositeList;
	protected IModel model;
	private Container parentContainer;

	public AView(IModel model) {
		super();
		setModel(model);
		((Observable) this.model).addObserver(this);
	}

	public void addChild(Container containerParent, Container containerChild,
			Object constraint) {
		containerParent.add(containerChild, constraint);
	}

	@Override
	public void addComposite(IView view) {
		compositeList.add(view);
	}

	@Override
	public IView getComposite(int index) {
		// TODO
		return null;
	}

	@Override
	public Container getParent() {
		return parentContainer;
	}

	@Override
	public void removeComposite(IView view) {
		int index = compositeList.indexOf(view);
		compositeList.remove(index);
	}

	@Override
	public void setModel(IModel model) {
		this.model = model;
	}

	@Override
	public void setParent(Container parentContainer) {
		this.parentContainer = parentContainer;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void uiComposite(IView viewComposite, Container parentContainer,
			Object constraint) {
		try {
			$class = (Class<Container>) Class.forName(viewComposite.getClass()
					.getPackage().getName()
					+ "." + viewComposite.getClass().getSimpleName());
			Method m = $class.getMethod("addChild", Container.class,
					Container.class, Object.class);
			if (viewComposite.getParent() != null) {
				m.invoke(viewComposite, viewComposite.getParent(),
						parentContainer, constraint);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		Iterator<IView> iterator = compositeList.iterator();
		while (iterator.hasNext()) {
			IView iView = iterator.next();
			iView.setParent(parentContainer);
			iView.ui();
		}
	}

	@Override
	public JPanel getFifoPanel() {
		Iterator<IView> iterator = compositeList.iterator();
		while (iterator.hasNext()) {
			IView iView = iterator.next();
			if (iView.getFifoPanel() != null)
				return iView.getFifoPanel();
		}
		return null;
	}

	@Override
	public JPanel getGrowthPanel() {
		Iterator<IView> iterator = compositeList.iterator();
		while (iterator.hasNext()) {
			IView iView = iterator.next();
			if (iView.getGrowthPanel() != null)
				return iView.getGrowthPanel();
		}
		return null;
	}

	@Override
	public JPanel getLifoPanel() {
		Iterator<IView> iterator = compositeList.iterator();
		while (iterator.hasNext()) {
			IView iView = iterator.next();
			if (iView.getLifoPanel() != null)
				return iView.getLifoPanel();
		}
		return null;
	}

	@Override
	public JPanel getMultiPanel() {
		Iterator<IView> iterator = compositeList.iterator();
		while (iterator.hasNext()) {
			IView iView = iterator.next();
			if (iView.getMultiPanel() != null)
				return iView.getMultiPanel();
		}
		return null;
	}

	@Override
	public JPanel getOffPanel() {
		Iterator<IView> iterator = compositeList.iterator();
		while (iterator.hasNext()) {
			IView iView = iterator.next();
			if (iView.getOffPanel() != null)
				return iView.getOffPanel();
		}
		return null;
	}

	@Override
	public JPanel getStdPanel() {
		Iterator<IView> iterator = compositeList.iterator();
		while (iterator.hasNext()) {
			IView iView = iterator.next();
			if (iView.getStdPanel() != null)
				return iView.getStdPanel();
		}
		return null;
	}

	@Override
	public void update(Observable o, Object arg) {
	}

}
